//
// Created by ZLY on 2025/3/29.
//

#ifndef QUEUE_H
#define QUEUE_H
#include <mutex>
#include <condition_variable>
#include <queue>
#include <Log.h>

template<typename T>
class Queue {
public:
    Queue() {
    };

    ~Queue() {
    };

    void Abort() {
        abort_ = 1;
        condition_.notify_all();
    }

    int Push(T val) {
        std::lock_guard<std::mutex> lock(mutex_);
        if (abort_ == 1) {
            return -1;
        }
        queue_.push(val);
        condition_.notify_all();
        return 0;
    }

    int Pop(T &val, const int timeout = 0) {
        std::unique_lock<std::mutex> lock(mutex_);
        if (queue_.empty()) {
            condition_.wait_for(lock, std::chrono::milliseconds(timeout), [&] {
                return !queue_.empty() | abort_;
            });
        }
        if (abort_ == 1) {
            return -1;
        }
        if (queue_.empty()) {
            return -2;
        }
        val = queue_.front();
        queue_.pop();
        return 0;
    }

    int Front(T &val) {
        std::unique_lock<std::mutex> lock(mutex_);
        if (abort_ == 1) {
            return -1;
        }
        if (queue_.empty()) {
            return -2;
        }
        val = queue_.front();
        return 0;
    }

    int Size() {
        std::unique_lock<std::mutex> lock(mutex_);
        return queue_.size();
    }

private:
    volatile int abort_ = 0;
    std::mutex mutex_;
    std::condition_variable condition_;
    std::queue<T> queue_;
};


#endif //QUEUE_H
